Generic Vapor Controllers

So we covered Generic Migrations in Fluent, but what if we wanted to add controllers to the mix. To make routes to our models.


Here’s an example:

Generic Controller Source

import Vapor
import Fluent

extension Continent : Parameter{}
extension Continent : Content{}

public final class ContinentsController<D>: RouteCollection where D: QuerySupporting, D: IndexSupporting  {
  
  public typealias Database = D
  
  public func boot(router: Router) throws {
    let aRoute = router.grouped("api", "continets")
    
    //GET /api/continets
    aRoute.get(use: getAllHandler)
    
    //GET /api/continets/:ID
    aRoute.get(Continent<D>.parameter as PathComponentsRepresentable, use: getOneHandler)
    
    //GET /api/continents/:continentID/countries
    aRoute.get(Continent<D>.parameter, "countries", use: getCountriesHandler)
  }
  
  //MARK: Handlers -
  
  func getAllHandler(_ req: Request) throws -> Future<[Continent<D>]> {
    return Continent<D>.query(on: req).all()
  }
  
  func getOneHandler(_ req: Request) throws -> Future<Continent<D>> {
    return try req.parameters.next(Continent<D>.self)
  }
  
  //MARK: Children Handler -
  
  func getCountriesHandler(_ req: Request) throws -> Future<[Country<D>]> {
    return try req.parameters.next(Continent<Database>.self).flatMap(to: [Country<D>].self) { continent in
      return try continent.countries.query(on: req).all()
    }
  }
  
  //MARK: Paginated Handlers -
  
  func getAllPaginatedHandler(_ req: Request) throws -> Future<[Continent<D>]> {
    return Continent<D>.query(on: req).all()
  }
  
  func getCountriesPaginatedHandler(_ req: Request) throws -> Future<[Country<Database>]> {
    return try req.parameters.next(Continent<Database>.self).flatMap(to: [Country<Database>].self) { continent in
      return try continent.countries.query(on: req).paginate(on: req).all()
    }
  }
  
}

(Example is from VaporCountries


Routing Generic Function

import Vapor
import Routing

public func addVaporCountriesRoutes<D>(for database: DatabaseIdentifier<D>, router: Router) throws where D: QuerySupporting & IndexSupporting & ReferenceSupporting {
  let continetsController = ContinentsController<D>()
  try router.register(collection: continetsController)
  
  let countriesController = CountriesController<D>()
  try router.register(collection: countriesController)
}

Usage

In routes.swift, just add code:

try addVaporCountriesRoutes(for: .sqlite, router: router)
//or
try addVaporCountriesRoutes(for: .psql, router: router)
//or
try addVaporCountriesRoutes(for: .mysql, router: router)


Prev: Vapor Controllers

Next:


Vapor 3 Tutorial Start



#pub #swift #controller #vapor #model #generic #routing